package objetos.aeronaves;

import java.util.Random;
import juego.Escenario;
import movimiento.Posicion;
import objetos.*;
import objetos.armas.*;
import objetos.proyectiles.*;
import org.jdom.*;
import vistas.FactoryVistas;
import ar.uba.fi.algo3.titiritero.ControladorJuego;
import ar.uba.fi.algo3.titiritero.vista.Imagen;
import auxiliares.Vector;

/*
 * Clase que modela al Algo42, el avi�n utilizado por el jugador.
 */
public class Algo42 extends ObjetoMovil {
	private int puntaje = 0;
	private int vidas = 5;
	private LaserCannon laser;
	private Torpedera torpedera;
	private Cohetera cohetera;

	public Algo42() {
		super();
		setTamanio(21);
		setEnergia(new Energia(100));
		setVelocidad(new Vector(-5, -5));
		setBando("aliado");
		this.laser = new LaserCannon(this, true);
		this.cohetera = new Cohetera(this, 0);
		this.torpedera = new Torpedera(this, 0);
	}

	public Algo42(Posicion posicion) {
		this();
		setPosicion(posicion);
	}

	public Algo42(int x, int y) {
		this(new Posicion(x, y));
	}

	@Override
	public void destruir() {
		/*
		 * El Algo42 tiene vidas. Solo se destruye cuando �stas bajan a 0. Se
		 * debe terminar el nivel cuando el Algo42 es destruido
		 */
		this.vidas--;
		if (this.vidas <= 0) {
			super.destruir();
			Escenario.getInstance().finNivel();
		} else {
			this.setChanged();
			notifyObservers();
			this.setEnergia(new Energia(100));
		}
	}

	@Override
	public void recuperarEnergia(Energia cantidad) {
		/* Si tiene la energ�a completa a�ade una vida */
		if (this.getEnergia().estaCompleta()) {
			this.vidas++;
		} else {
			super.recuperarEnergia(cantidad);
		}
	}

	public void colisionCon(ObjetoNoControlado objeto) {
		objeto.colisionConAlgo42(this);
	}

	public void modificarPuntaje(int puntos) {
		this.puntaje += puntos;
	}

	/* Manejo de armas */
	public void agregarArma(LaserCannon arma) {
		this.laser.mejorar();
	}

	public void agregarArma(Torpedera torpedera) {
		int cantTorpedos = torpedera.getBalas();
		int cantRastreadores = torpedera.getCantRastreadores();
		int cantAdaptables = torpedera.getCantAdaptables();

		this.torpedera.recargar(cantTorpedos);
		this.torpedera.recargarRastreador(cantRastreadores);
		this.torpedera.recargarAdaptables(cantAdaptables);
	}

	public void agregarArma(Cohetera cohetera) {
		this.cohetera.recargar(cohetera.getBalas());
	}

	public int obtenerPotenciaLaser() {
		return this.laser.getPoder();
	}

	public int obtenerMuninicionTorpedos() {
		return this.torpedera.getBalas();
	}

	public int obtenerMuninicionRastreadores() {
		return this.torpedera.getCantRastreadores();
	}

	public int obtenerMuninicionAdaptables() {
		return this.torpedera.getCantAdaptables();
	}

	public int obtenerMuninicionCohetes() {
		return this.cohetera.getBalas();
	}

	/* Annotation para que no moleste porque no se uso el metodo */
	@SuppressWarnings("unused")
	private Arma obtenerArmaRandom() {
		Random rdm = new Random();
		int num = rdm.nextInt(2);
		switch (num) {
		case 0:
			return this.torpedera;
		case 1:
			return this.cohetera;
		default:
			return this.laser;
		}
	}

	/* Movimiento */
	public void moverArriba() {
		int vY = getVelocidad().getComponenteY();
		int yFinal = getPosicion().getEnY() - vY * Integer.signum(vY);
		if (yFinal >= 0) {
			getPosicion().setEnY(yFinal);
		}
	}

	public void moverAbajo() {
		int vY = getVelocidad().getComponenteY();
		int yFinal = getPosicion().getEnY() + vY * Integer.signum(vY);
		if (yFinal + getTamanio() <= Escenario.getInstance().getMaxY()) {
			getPosicion().setEnY(yFinal);
		}
	}

	public void moverIzquierda() {
		int vX = getVelocidad().getComponenteX();
		int xFinal = getPosicion().getEnX() - vX * Integer.signum(vX);
		if (xFinal >= 0) {
			getPosicion().setEnX(xFinal);
		}
	}

	public void moverDerecha() {
		int vX = getVelocidad().getComponenteX();
		int xFinal = getPosicion().getEnX() + vX * Integer.signum(vX);
		if (xFinal + getTamanio() <= Escenario.getInstance().getMaxX()) {
			getPosicion().setEnX(xFinal);
		}
	}

	public void darVuelta() {
		int vX = this.getVelocidad().getComponenteX();
		int vY = this.getVelocidad().getComponenteY();
		this.setVelocidad(new Vector(-1 * vX, -1 * vY));

		this.setChanged();
		notifyObservers();
	}

	/* Disparo */
	public void dispararLaser() {
		LaserShoot laser = this.getLaser().disparar();
		int correccionDeVistaX = this.getPosicion().getEnX() - this.getX();
		int correccionDeVistaY = this.getPosicion().getEnY() - this.getY();
		Posicion pos = new Posicion(this.getPosicion().getEnX()
				+ correccionDeVistaX, this.getPosicion().getEnY()
				+ correccionDeVistaY);
		laser.setPosicion(pos);
		Escenario.getInstance().agregarObjeto(laser);
	}

	public void dispararTorpedo() {
		Proyectil proyectil = this.torpedera.dispararTorpedo();
		if (proyectil == null) {
			return;
		}
		int correccionDeVistaY = this.getPosicion().getEnY() - this.getY();
		Posicion pos = new Posicion(this.getPosicion().getEnX(), this
				.getPosicion().getEnY()
				+ correccionDeVistaY);
		proyectil.setPosicion(pos);
		Escenario.getInstance().agregarObjeto(proyectil);
	}

	public void dispararRastreador() {
		Proyectil proyectil = this.torpedera.dispararRastreador();
		if (proyectil == null) {
			return;
		}
		int correccionDeVistaX = this.getPosicion().getEnX() - this.getX();
		int correccionDeVistaY = this.getPosicion().getEnY() - this.getY();
		Posicion pos = new Posicion(this.getPosicion().getEnX()
				+ correccionDeVistaX * 2, this.getPosicion().getEnY()
				+ correccionDeVistaY);
		proyectil.setPosicion(pos);
		Escenario.getInstance().agregarObjeto(proyectil);
	}

	public void dispararAdaptable() {
		Proyectil proyectil = this.torpedera.dispararAdaptable();
		if (proyectil == null) {
			return;
		}
		int correccionDeVistaX = this.getPosicion().getEnX() - this.getX();
		int correccionDeVistaY = this.getPosicion().getEnY() - this.getY();
		Posicion pos = new Posicion(this.getPosicion().getEnX()
				+ correccionDeVistaX * 2, this.getPosicion().getEnY()
				+ correccionDeVistaY);
		proyectil.setPosicion(pos);
		Escenario.getInstance().agregarObjeto(proyectil);
	}

	public void dispararCohetera() {
		Proyectil proyectil = this.cohetera.disparar();
		if (proyectil == null) {
			return;
		}
		int correccionDeVistaY = this.getPosicion().getEnY() - this.getY();
		Posicion pos = new Posicion(this.getPosicion().getEnX(), this
				.getPosicion().getEnY()
				+ correccionDeVistaY);
		proyectil.setPosicion(pos);
		Escenario.getInstance().agregarObjeto(proyectil);
	}

	@Override
	public Imagen darVista(ControladorJuego controlador) {
		return FactoryVistas.crearVista(this, controlador);
	}

	public int getPuntaje() {
		return puntaje;
	}

	public void setPuntaje(int puntaje) {
		this.puntaje = puntaje;
	}

	public void setLaser(LaserCannon laser) {
		this.laser = laser;
	}

	public LaserCannon getLaser() {
		return laser;
	}

	public int getVidas() {
		return vidas;
	}

	public void setVidas(int vidas) {
		this.vidas = vidas;
	}

	/* Persistencia */
	@Override
	public Element obtenerNodo() {
		Element nodo = new Element("algo42");

		nodo
				.setAttribute(new Attribute("puntaje", String
						.valueOf(this.puntaje)));
		nodo.setAttribute(new Attribute("vidas", String.valueOf(this.vidas)));
		nodo.setAttribute(new Attribute("posicionX", Integer.toString(this
				.getPosicion().getEnX())));
		nodo.setAttribute(new Attribute("posicionY", Integer.toString(this
				.getPosicion().getEnY())));

		nodo.addContent(this.getEnergia().obtenerNodo());

		nodo.addContent(this.laser.obtenerNodo());
		nodo.addContent(this.cohetera.obtenerNodo());
		nodo.addContent(this.torpedera.obtenerNodo());

		return nodo;
	}

	public Algo42(Element nodo) {
		this(Integer.parseInt(nodo.getAttributeValue("posicionX")), Integer
				.parseInt(nodo.getAttributeValue("posicionY")));

		this.vidas = Integer.parseInt(nodo.getAttributeValue("vidas"));
		this.puntaje = Integer.parseInt(nodo.getAttributeValue("puntaje"));
		this.setBando("aliado");
		this.setEnergia(new Energia(nodo.getChild("energia")));

		this.laser = new LaserCannon(nodo.getChild("laserCannon"));
		this.laser.setBase(this);
		this.cohetera = new Cohetera(nodo.getChild("cohetera"));
		this.cohetera.setBase(this);
		this.torpedera = new Torpedera(nodo.getChild("torpedera"));
		this.torpedera.setBase(this);
	}

}
